package main

import (
	"crypto/md5"
	"crypto/sha256"
	_ "embed"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"log"
	"os"
	"strings"
	"sync"

	"github.com/getlantern/systray"
	"github.com/google/uuid"
	"gitverse.ru/shakmaev/keycloud/internal/keys"
	"gitverse.ru/shakmaev/keycloud/internal/password"
	"golang.design/x/clipboard"
	"golang.design/x/hotkey"
	"golang.design/x/hotkey/mainthread"
)

//go:embed kc.png
var kcIcon []byte

var hkList = []*hotkey.Hotkey{
	hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyU),
	hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyB),
	hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyM),
	hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyP),
	hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeyS),
}

func main() {
	//workingDirectory, _ := filepath.Abs("")
	//pathTo := fmt.Sprintf("%s/KeyCloud.app", workingDirectory)
	//log.Println(pathTo)
	//app = &autostart.App{
	//	Name:        "KeyCloud",
	//	DisplayName: "KeyCloud",
	//	Exec:        []string{"open", pathTo},
	//}

	//config := &service.Config{
	//	ExecutableName:   "ru.shakmaev.keycloud",
	//	WorkingDirectory: workingDirectory,
	//	Name:             "ru.shakmaev.keycloud",
	//	DisplayName:      "KeyCloud",
	//	LongDescription:  "KeyCloud - make smart your coding",
	//
	//	Init:  InitService,
	//	Start: StartService,
	//	Stop:  StopService,
	//}
	//
	//config.Run()

	err := clipboard.Init()
	if err != nil {
		log.Println(err)
		os.Exit(0)
	}

	mainthread.Init(fn)
}

func onReady() {
	systray.SetIcon(kcIcon)
	systray.SetTooltip("KeyCloud")
	//mLogin := systray.AddMenuItemCheckbox("Автозапуск", "", app.IsEnabled())
	//
	//systray.AddSeparator()
	mQuit := systray.AddMenuItem("Выход", "")

	go func() {
		<-mQuit.ClickedCh
		systray.Quit()
	}()

	//go func() {
	//	<-mLogin.ClickedCh
	//	if app != nil {
	//		if app.IsEnabled() {
	//			mLogin.Uncheck()
	//			log.Println("App is already enabled, removing it...")
	//
	//			if err := app.Disable(); err != nil {
	//				log.Fatal(err)
	//			}
	//		} else {
	//			log.Println("Enabled app")
	//			mLogin.Check()
	//
	//			if err := app.Enable(); err != nil {
	//				log.Fatal(err)
	//			}
	//		}
	//	}
	//}()

}

//func InitService() error {
//	fmt.Println("Service Init")
//
//	return nil
//}
//
//// StartService is called by the ServiceManager when the server is ready to start
//func StartService() error {
//	fmt.Println("Service Started\n")
//	mainthread.Init(fn)
//
//	return nil
//}

func job(hk *hotkey.Hotkey) {
	log.Println("job started")
	if err := hk.Register(); err != nil {
		return
	}
	for range hk.Keydown() {
		switch {
		case strings.Contains(hk.String(), fmt.Sprintf("%d+", hotkey.KeyU)):
			//UUID generator
			id := uuid.New()
			paste(id.String())
		case strings.Contains(hk.String(), fmt.Sprintf("%d+", hotkey.KeyB)):
			//Clipboard from/to Base64 and Paste
			keyBase64 := clipboard.Read(clipboard.FmtText)
			if len(keyBase64) > 0 {
				resultDecode, err := base64.StdEncoding.DecodeString(string(keyBase64))
				result := string(resultDecode)
				if err != nil {
					result = base64.StdEncoding.EncodeToString(keyBase64)
				}
				paste(result)
			}
		case strings.Contains(hk.String(), fmt.Sprintf("%d+", hotkey.KeyM)):
			//Clipboard to Md5 and Paste
			toMd5 := clipboard.Read(clipboard.FmtText)
			if len(toMd5) > 0 {
				hash := md5.Sum(toMd5)
				paste(hex.EncodeToString(hash[:]))
			}
		case strings.Contains(hk.String(), fmt.Sprintf("%d+", hotkey.KeyP)):
			//Password Generator
			res, err := password.Generate(20, 8, 4, false, false)
			if err != nil {
				log.Fatal(err)
			}
			paste(res)
		case strings.Contains(hk.String(), fmt.Sprintf("%d+", hotkey.KeyS)):
			//Clipboard to Sha256 and Paste
			toSum := clipboard.Read(clipboard.FmtText)
			if len(toSum) > 0 {
				sum := sha256.Sum256(toSum)
				result := fmt.Sprintf("%x", sum)
				paste(result)
			}

		}
	}
}

func fn() {
	wg := sync.WaitGroup{}
	for _, hk := range hkList {
		wg.Add(1)
		go func(hk *hotkey.Hotkey) {
			defer wg.Done()
			job(hk)
		}(hk)
	}

	go func() {
		systray.Run(onReady, func() {})
	}()

	wg.Wait()
}

//
//func StopService() error {
//	log.Println("Service Stopping")
//	cf()
//	if len(hkList) > 0 {
//		for _, hk := range hkList {
//			_ = hk.Unregister()
//		}
//	}
//	fmt.Println("Service Stopped\n")
//	return nil
//}

func paste(s string) {
	clipboard.Write(clipboard.FmtText, []byte(s))
	keys.ClipboardPaste()
}
